Conversation
…ger to input balancer address
…tyling variables for the desktop app, style the view cluster config view
… on the same ports
…sktop app service bridges
…cer with an empty state, rename balancer to cluster in user-facing code
# Conflicts: # Cargo.lock # Makefile # paddler/src/cmd/agent.rs # paddler/src/lib.rs
This reverts commit f2ba99c.
This reverts commit aebfd22.
# Conflicts: # Makefile # paddler/src/agent/continuous_batch_scheduler.rs # paddler_model_tests/tests/continuous_batch_clean_shutdown.rs
There was a problem hiding this comment.
Pull request overview
This PR introduces a new iced-based desktop GUI (“Second Brain”) for starting/joining and monitoring a Paddler cluster, while refactoring the existing CLI wiring into a dedicated paddler_cli crate with shared bootstrap logic extracted into paddler_bootstrap.
Changes:
- Add
paddler_second_brain_gui(iced app) with screens for home/start/join/running cluster + agent status UI. - Add
paddler_bootstrapto centralize agent/balancer service wiring; refactor CLI to use it and removepaddler::cmd. - Update workspace + supporting scripts/tests/assets (fonts, icons, images) for the new GUI and new
paddler_clibinary name.
Reviewed changes
Copilot reviewed 58 out of 69 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| resources/images/join_a_cluster.png | Adds GUI image asset. |
| resources/images/create_a_cluster.png | Adds GUI image asset. |
| resources/icons/stop.svg | Adds stop icon used by GUI buttons. |
| resources/icons/copy.svg | Adds copy icon used by GUI buttons. |
| resources/css/_fonts.css | Switches JetBrains Mono font loading to local TTFs (and adds bold face). |
| paddler_types/src/agent_controller_snapshot.rs | Adds Clone/Debug derives for snapshot type used in GUI rendering/state. |
| paddler_second_brain_gui/src/ui/view_start_cluster_config.rs | Start-cluster form UI (addresses + model pick list). |
| paddler_second_brain_gui/src/ui/view_running_cluster.rs | Running-cluster UI (copy address, stop cluster, list agents). |
| paddler_second_brain_gui/src/ui/view_join_cluster_config.rs | Join-cluster form UI (address, agent name, slots). |
| paddler_second_brain_gui/src/ui/view_home.rs | Home UI with “Start/Join” tiles and images. |
| paddler_second_brain_gui/src/ui/view_form_field.rs | Shared form-field wrapper with label and optional error rendering. |
| paddler_second_brain_gui/src/ui/view_agent_running.rs | Agent-running UI (connection status + disconnect). |
| paddler_second_brain_gui/src/ui/view_agent_card.rs | Agent status card UI (download progress/status/slots). |
| paddler_second_brain_gui/src/ui/variables.rs | Central UI constants (spacing, colors, font sizes). |
| paddler_second_brain_gui/src/ui/style_status_indicator.rs | Status indicator styling. |
| paddler_second_brain_gui/src/ui/style_field_text_input.rs | Text input styling for forms. |
| paddler_second_brain_gui/src/ui/style_field_pick_list_menu.rs | Pick-list menu styling. |
| paddler_second_brain_gui/src/ui/style_field_pick_list.rs | Pick-list control styling. |
| paddler_second_brain_gui/src/ui/style_field_container.rs | Form field container styling. |
| paddler_second_brain_gui/src/ui/style_download_progress_bar.rs | Progress bar styling for downloads. |
| paddler_second_brain_gui/src/ui/style_card_container.rs | Card/container styling used by cluster address card. |
| paddler_second_brain_gui/src/ui/style_button_primary.rs | Primary button styling. |
| paddler_second_brain_gui/src/ui/style_button_disconnect.rs | Disconnect/stop button styling. |
| paddler_second_brain_gui/src/ui/style_agent_container.rs | Agent card container styling. |
| paddler_second_brain_gui/src/ui/mod.rs | Exposes UI modules for the GUI crate. |
| paddler_second_brain_gui/src/ui/font.rs | Defines JetBrains Mono regular/bold iced::Font constants. |
| paddler_second_brain_gui/src/start_cluster_config_handler.rs | Start-cluster form validation + action generation. |
| paddler_second_brain_gui/src/start_cluster_config_data.rs | Start-cluster form state model. |
| paddler_second_brain_gui/src/second_brain.rs | Main iced app: state machine integration, task spawning for cluster/agent, clipboard, subscriptions. |
| paddler_second_brain_gui/src/screen.rs | State-machine definition + transitions between screens. |
| paddler_second_brain_gui/src/running_cluster_handler.rs | Running-cluster message/action handling (stop/copy/snapshot updates). |
| paddler_second_brain_gui/src/running_cluster_data.rs | Running-cluster state model. |
| paddler_second_brain_gui/src/network_interface_address.rs | Model type for detected interfaces. |
| paddler_second_brain_gui/src/model_preset.rs | Model preset list + conversion to BalancerDesiredState. |
| paddler_second_brain_gui/src/message.rs | Top-level iced message enum wiring screen handlers + lifecycle events. |
| paddler_second_brain_gui/src/main.rs | GUI binary entrypoint (fonts, theme, window size, subscription). |
| paddler_second_brain_gui/src/join_cluster_config_handler.rs | Join-cluster form validation + connect action generation. |
| paddler_second_brain_gui/src/join_cluster_config_data.rs | Join-cluster form state model. |
| paddler_second_brain_gui/src/home_handler.rs | Home screen message/action mapping. |
| paddler_second_brain_gui/src/home_data.rs | Home screen state model. |
| paddler_second_brain_gui/src/detect_network_interfaces.rs | Detects non-loopback IPv4 interfaces to suggest bind address. |
| paddler_second_brain_gui/src/current_screen.rs | Tracks current typed screen instance + default initialization. |
| paddler_second_brain_gui/src/agent_running_handler.rs | Agent-running handler for status updates/disconnect. |
| paddler_second_brain_gui/src/agent_running_data.rs | Agent-running state model + snapshot application. |
| paddler_second_brain_gui/Cargo.toml | Adds new GUI crate configuration/dependencies. |
| paddler_integration_tests/src/lib.rs | Updates default binary path to paddler_cli. |
| paddler_cli/src/main.rs | Switches CLI to local cmd module instead of paddler::cmd. |
| paddler_cli/src/cmd/value_parser/parse_socket_addr.rs | Uses paddler::resolved_socket_addr::ResolvedSocketAddr after refactor. |
| paddler_cli/src/cmd/value_parser/parse_duration.rs | Adds duration parser helper (milliseconds). |
| paddler_cli/src/cmd/value_parser/mod.rs | Exposes value parsers. |
| paddler_cli/src/cmd/mod.rs | Declares CLI command modules. |
| paddler_cli/src/cmd/handler.rs | Defines Handler trait for CLI subcommands. |
| paddler_cli/src/cmd/balancer.rs | Refactors balancer command to use paddler_bootstrap::bootstrap_balancer. |
| paddler_cli/src/cmd/agent.rs | Adds agent command using paddler_bootstrap::bootstrap_agent. |
| paddler_cli/Cargo.toml | Adds new CLI crate configuration/dependencies/features. |
| paddler_bootstrap/src/lib.rs | New crate module exports for shared bootstrapping. |
| paddler_bootstrap/src/bootstrapped_balancer_handle.rs | Implements shared balancer bootstrap wiring + returns handle. |
| paddler_bootstrap/src/bootstrapped_agent_handle.rs | Implements shared agent bootstrap wiring + returns handle. |
| paddler_bootstrap/src/bootstrap_balancer_params.rs | Defines params struct for balancer bootstrap. |
| paddler_bootstrap/src/bootstrap_agent_params.rs | Defines params struct for agent bootstrap. |
| paddler_bootstrap/Cargo.toml | Adds new bootstrap crate configuration/dependencies/features. |
| paddler/src/lib.rs | Removes pub mod cmd from library API. |
| paddler/src/cmd/agent.rs | Removes legacy CLI agent implementation from library. |
| paddler/Cargo.toml | Removes unused nix dependency. |
| jarmuz/worker-paddler.mjs | Updates spawned binary name from paddler to paddler_cli. |
| Cargo.toml | Registers new workspace members and adds workspace deps for iced/if-addrs/statum + paddler_bootstrap. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ), | ||
| Task::done(Message::ClusterStarted), | ||
| Task::stream(iced::stream::channel(1, async move |mut output| { |
There was a problem hiding this comment.
Task::done(Message::ClusterStarted) fires immediately, so the UI transitions to “Running cluster” even if bootstrap_balancer(...) fails or hasn’t finished binding sockets yet. This can cause brief incorrect UI state and makes “started” mean “start initiated” rather than “cluster is ready”. Consider emitting ClusterStarted only after the balancer has successfully bootstrapped (e.g., after bootstrap_balancer returns OK / after the pool watch has been populated) and remove the unconditional Task::done.
| fn is_port_in_use(address: &SocketAddr) -> bool { | ||
| TcpListener::bind(address).is_err() | ||
| } |
There was a problem hiding this comment.
is_port_in_use treats any bind failure as “port is already in use”. TcpListener::bind can also fail for other reasons (e.g., address not available on this host, permission denied), which would surface a misleading “Port X is already in use” error in the UI. Consider checking the io::ErrorKind for AddrInUse specifically (and handling other error kinds with a different message), or returning a Result so the caller can distinguish the failure reason.
No description provided.